package se.webbzon.oschi01.gui;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import se.webbzon.oschi01.action.DefaultAction;
import se.webbzon.oschi01.command.Command;
import se.webbzon.oschi01.nbt.Tag;
import se.webbzon.oschi01.nbt.Tags;
import se.webbzon.oschi01.singleton.Singletons;

public abstract class NBTPopupDialog<T> {
	
	protected final JDialog dialog;
	
	protected final Tag<T> nbtTag;
	
	public NBTPopupDialog(Tag<T> nbtTag) {
		this.dialog = new JDialog(Singletons.instance(MainFrame.class));
		this.nbtTag = nbtTag;
	}
	
	public void setVisible(boolean visible) {
		dialog.setVisible(visible);
	}
	
	public boolean isVisible() {
		return dialog.isVisible();
	}
	
	public void dispose() {
		dialog.dispose();
	}
	
	protected abstract T getValue();
	
	protected abstract void setValue(T t);
	
	protected void createDefaultLayout() {
		createDefaultLayout(null);
	}
	
	protected void createDefaultLayout(JComponent centerComponent) {
		dialog.setAlwaysOnTop(true);
		dialog.setTitle("Value of \"" + nbtTag + "\"");
		dialog.setLayout(new BorderLayout());
		
		JPanel topPanel = new JPanel();
		topPanel.setLayout(new GridLayout(3,1));
		topPanel.add(new JLabel("Tag path:"));
		JTextField textField = new JTextField(Tags.getPath(nbtTag));
		textField.setEditable(false);
		topPanel.add(textField);
		
		JPanel bottomPanel = new JPanel();
		bottomPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
		
		if (centerComponent != null) {
			bottomPanel.add(new JButton(new OkAction()));
			topPanel.add(new JLabel("Tag value:"));
			dialog.add(centerComponent);
			bottomPanel.add(new JButton(new ApplyAction()));
		} else
			bottomPanel.add(new JButton(new CloseAction("OK")));
		bottomPanel.add(new JButton(new CloseAction("Close")));
		dialog.add(topPanel,BorderLayout.NORTH);
		dialog.add(bottomPanel,BorderLayout.SOUTH);
		dialog.pack();
	}
	
	protected class CloseAction extends AbstractAction {
		
		/**
		 * 
		 */
		private static final long serialVersionUID = 2626086758827762370L;

		public CloseAction(String name) {
			putValue(Action.NAME,name);
		}

		@Override public void actionPerformed(ActionEvent e) {
			dispose();
		}
		
	}
	
	protected class ApplyAction extends DefaultAction {
		
		/**
		 * 
		 */
		private static final long serialVersionUID = -406501999040606669L;

		public ApplyAction() {
			putValue(Action.NAME,"Apply");
			setListener(Singletons.instance(MainFrame.class).getModel().getHistory());
		}

		@Override public void actionPerformed(ActionEvent arg0) {
			performCommand(new ApplyCommand(NBTPopupDialog.this.getValue()));
		}
		
	}
	
	protected class OkAction extends DefaultAction {

		/**
		 * 
		 */
		private static final long serialVersionUID = 5880774791815899931L;

		public OkAction() {
			putValue(Action.NAME,"OK");
			setListener(Singletons.instance(MainFrame.class).getModel().getHistory());
		}

		@Override public void actionPerformed(ActionEvent e) {
			performCommand(new ApplyCommand(NBTPopupDialog.this.getValue()));
			dispose();
		}
		
	}
	
	protected class ApplyCommand implements Command {
		
		T newValue, oldValue;
		
		public ApplyCommand(T newValue) {
			this.newValue = newValue;
		}

		@Override public String getName() {
			return "change " + nbtTag;
		}

		@Override public void redo() {
			oldValue = nbtTag.getValue();
			nbtTag.setValue(newValue);
			setValue(newValue);
		}

		@Override public void undo() {
			nbtTag.setValue(oldValue);
			setValue(oldValue);
		}
		
	}

}
